package com.webbdong.aop.agent.test.jvm;


import com.sun.deploy.util.StringUtils;
import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.VirtualMachine;
import sun.tools.attach.HotSpotVirtualMachine;
import org.apache.commons.io.IOUtils;
import sun.tools.attach.WindowsVirtualMachine;

import javax.management.MBeanServerConnection;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import java.io.IOException;
import java.io.InputStream;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryPoolMXBean;
import java.lang.management.MemoryType;
import java.lang.management.MemoryUsage;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @program: spring-agent
 * @description:
 * @author: zt22328 赵儒定
 * @create: 2023-04-03 09:59
 **/
public class JvmUtils {

    public static void main(String[] args) throws IOException, AttachNotSupportedException {
//        VirtualMachine.list().forEach(System.out::println);
//        VirtualMachine virtualMachine = VirtualMachine.attach("50760");
//        System.out.println(virtualMachine.startLocalManagementAgent());
        getMemory("50760");
//        VirtualMachineImpl
//        System.out.println();


    }

    /* 获取各种内存信息,  jmap -heap pid */
    public static void  getMemory(String pid ) throws IOException, AttachNotSupportedException {
        VirtualMachine virtualMachine = VirtualMachine.attach(pid);
        String address = virtualMachine.startLocalManagementAgent();
        try {
            JMXServiceURL target = new JMXServiceURL(address);
            final JMXConnector connector = JMXConnectorFactory.connect(target);
            final MBeanServerConnection mbsc = connector.getMBeanServerConnection();
//            connector.close();
            TimeUnit.SECONDS.sleep(1);

            List<MemoryPoolMXBean> memoryPoolMXBeans = ManagementFactory.getPlatformMXBeans(mbsc , MemoryPoolMXBean.class);
            for (MemoryPoolMXBean memoryPoolMXBean : memoryPoolMXBeans) {
                String name = memoryPoolMXBean.getName();
                String[] memoryManagerNames = memoryPoolMXBean.getMemoryManagerNames();
                MemoryType type = memoryPoolMXBean.getType();
                MemoryUsage usage = memoryPoolMXBean.getUsage();
                MemoryUsage peakUsage = memoryPoolMXBean.getPeakUsage();

                System.out.println(name + ":");
                System.out.println("    managers: " + StringUtils.join(Arrays.asList(memoryManagerNames) , " , "));
                System.out.println("    type: " + type.toString());
                System.out.print("    usage: " + usage.toString());
                System.out.println("    Percentage: " + ((double) usage.getUsed() / usage.getCommitted() ) );
                System.out.println("    peakUsage: "  +peakUsage.toString());

                System.out.println("");
            }

        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /* 获取 jstack 堆信息*/
    public static String getStack(String pid){
        VirtualMachine virtualMachine = null ;
        InputStream is = null ;
        try{
            virtualMachine = VirtualMachine.attach(pid) ;
            HotSpotVirtualMachine machine = (HotSpotVirtualMachine) virtualMachine ;
            is = machine.remoteDataDump(new String[]{});
            return IOUtils.toString(is , StandardCharsets.UTF_8.name());
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            IOUtils.closeQuietly(is);
        }
        return null ;
    }
    /*  获取 heapHisto 信息 */
    public static String heapHisto(String pid){
        VirtualMachine virtualMachine = null ;
        InputStream is = null ;
        try{
            virtualMachine = VirtualMachine.attach(pid) ;
            HotSpotVirtualMachine machine = (HotSpotVirtualMachine) virtualMachine ;
            is = machine.heapHisto(new String[]{});
            return IOUtils.toString(is , StandardCharsets.UTF_8.name());
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            IOUtils.closeQuietly(is);
        }
        return null ;
    }

    public static String jCmd(String pid){
        VirtualMachine virtualMachine = null ;
        InputStream is = null ;
        try{
            virtualMachine = VirtualMachine.attach(pid) ;
            HotSpotVirtualMachine machine = (HotSpotVirtualMachine) virtualMachine ;
            is = machine.executeJCmd(new String());
            return IOUtils.toString(is , StandardCharsets.UTF_8.name());
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            IOUtils.closeQuietly(is);
        }
        return null ;
    }

    public static String cmd(String pid, String cmd, String ... opts){
        VirtualMachine virtualMachine = null ;
        InputStream is = null ;
        try{
            virtualMachine = VirtualMachine.attach(pid) ;
            HotSpotVirtualMachine machine = (HotSpotVirtualMachine) virtualMachine ;
            Method execute = WindowsVirtualMachine.class
                    .getDeclaredMethod("execute", String.class, Object[].class);
            execute.setAccessible(true);
            is = (InputStream) execute.invoke(machine, cmd, opts);
            return IOUtils.toString(is , StandardCharsets.UTF_8.name());
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            IOUtils.closeQuietly(is);
        }
        return null ;
    }

}
